﻿using System;
using System.DirectoryServices;
using System.IO;

namespace uTILLIty.ADExtractor.Core.Exporters.Csv
{
	public class CsvExporter : ExporterBase<CsvExporterConfiguration>
	{
		internal Stream DefaultStream;
		

		public override void Export(QueryInformation query, SearchResultCollection searchResults, CsvExporterConfiguration config)
		{
			if (config == null)
				config = new CsvExporterConfiguration();

			StreamWriter writer;
			bool closeWriter = GetOutputStream(config, out writer);
			try
			{
				foreach (var prop in query.PropertiesToLoad)
				{
					writer.Write(CsvEncode(config, prop.DisplayName));
				}
				writer.Write(CsvEncode(config, "Path"));
				writer.WriteLine();
				foreach (SearchResult item in searchResults)
				{
					foreach (var prop in query.PropertiesToLoad)
					{
						writer.Write(CsvEncode(config, ActiveDirectoryExtractor.GetValue(item, prop, query)));
					}
					writer.Write(CsvEncode(config, item.Path));
					writer.WriteLine();
				}
				writer.Flush();
			}
			finally
			{
				if (closeWriter)
					writer.Close();
			}
		}

		private string CsvEncode(CsvExporterConfiguration config, object value)
		{
			if (value == null)
				return string.Empty;

			var stringValue = value.ToString();
			var enquot = config.ValueEnquotation;
			if (enquot == ValueEnquotationType.None && stringValue.Contains(config.Separator))
				enquot = ValueEnquotationType.DoubleQuotes;

			switch (enquot)
			{
				case ValueEnquotationType.None:
					return string.Format("{0}{1}", stringValue, config.Separator);
				case ValueEnquotationType.SingleQuotes:
					return string.Format("{2}{0}{2}{1}", stringValue.Replace("'", "''"), config.Separator, "'");
				case ValueEnquotationType.DoubleQuotes:
					return string.Format("{2}{0}{2}{1}", stringValue.Replace("\"", "\"\""), config.Separator, "\"");
				default:
					throw new ArgumentOutOfRangeException();
			}
		}

		private bool GetOutputStream(CsvExporterConfiguration config, out StreamWriter writer)
		{
			writer = string.IsNullOrWhiteSpace(config.OutputFilename)
				? new StreamWriter(DefaultStream ?? Console.OpenStandardOutput(), config.EncodingParsed)
				: new StreamWriter(config.OutputFilename, false, config.EncodingParsed);

			return !string.IsNullOrWhiteSpace(config.OutputFilename);
		}
	}
}